home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-04  |  12.1 KB  |  639 lines

  1. #include <ctype.h>
  2. #include <dir.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <dos.h>
  7. #include <io.h>
  8. #ifdef __GO32__
  9. #include <sys/farptr.h>
  10. #else
  11. #include <alloc.h>
  12. #endif
  13.  
  14. #define extern
  15. #include "glob.h"
  16. #undef extern
  17. int (*__glob_sense_expand_from_proxy)(int original_expand_wildcards) = 0;
  18. static int expand_wildcards = 0;
  19.  
  20. static void parse_chars(void *ptr, int (*func)(void *ptr));
  21.  
  22. static int argv_max = 0;
  23.  
  24. static int
  25. string_getc(void *ptr)
  26. {
  27.   int c = *(*(char **)ptr)++;
  28.   return c;
  29. }
  30.  
  31. static int
  32. file_getc(void *ptr)
  33. {
  34.   return fgetc((FILE *)ptr);
  35. }
  36.  
  37. static char *
  38. get_proxy(int i)
  39. {
  40.   int len;
  41.   char *rv;
  42.   int seg = __glob_proxy_vals[1];
  43.   int ofs = __glob_proxy_vals[2];
  44.   int c;
  45. #ifdef __GO32__
  46.   _farsetsel(_go32_conventional_mem_selector());
  47.   ofs = seg * 16 + _farnspeekw(seg*16+ofs+2*i);
  48.   for (len=0; _farnspeekb(ofs+len); len++);
  49.   rv = (char *)malloc(len+1);
  50.   if (!rv)
  51.   {
  52.     fprintf(stderr, "Error: out of memory gathering arguments\n");
  53.     exit(1);
  54.   }
  55.   for (len=0; (c = _farnspeekb(ofs+len)) != 0; len++)
  56.     rv[len] = c;
  57.   rv[len] = 0;
  58. #else
  59.   ofs = peek(seg, ofs+2*i);
  60.   for (len=0; peekb(seg, ofs+len); len++);
  61.   rv = (char *)malloc(len+1);
  62.   if (!rv)
  63.   {
  64.     fprintf(stderr, "Error: out of memory gathering arguments\n");
  65.     exit(1);
  66.   }
  67.   for (len=0; (c = peekb(seg, ofs+len)) != 0; len++)
  68.     rv[len] = c;
  69.   rv[len] = 0;
  70. #endif
  71.   return rv;
  72. }
  73.  
  74. static void
  75. stash_arg_at(char *arg, int slot, int dup)
  76. {
  77.   if (__glob_argv == 0)
  78.     argv_max = 0;
  79.   if (slot >= argv_max)
  80.   {
  81.     int newmax = (argv_max + 1)*2;
  82.     if (__glob_argv)
  83.       __glob_argv = (char **)realloc(__glob_argv, newmax * sizeof(char *));
  84.     else
  85.     {
  86.       __glob_argv = (char **)malloc(newmax * sizeof(char *));
  87.       __glob_argc = 0;
  88.       argv_max = 0;
  89.     }
  90.     if (!__glob_argv)
  91.     {
  92.       fprintf(stderr, "Error: out of memory gathering arguments\n");
  93.       exit(1);
  94.     }
  95.     while (argv_max < newmax)
  96.       __glob_argv[argv_max++] = 0;
  97.   }
  98.   __glob_argv[slot] = arg ? (dup ? strdup(arg) : arg) : 0;
  99.   if (arg && !__glob_argv[slot])
  100.   {
  101.     fprintf(stderr, "Error: out of memory gathering arguments\n");
  102.     exit(1);
  103.   }
  104.   if (arg && (slot >= __glob_argc))
  105.     __glob_argc = slot + 1;
  106. }
  107.  
  108. static void
  109. stash_arg(char *arg)
  110. {
  111.   stash_arg_at(arg, __glob_argc ? __glob_argc : 1, 1);
  112. }
  113.  
  114. static void
  115. free_args(void)
  116. {
  117.   int i;
  118.   for (i=0; i<argv_max; i++)
  119.     if (__glob_argv[i])
  120.     {
  121.       free(__glob_argv[i]);
  122.       __glob_argv[i] = 0;
  123.     }
  124.   __glob_argc = 0;
  125. }
  126.  
  127. #define SINGLE_QUOTE '\''
  128. #define DOUBLE_QUOTE '"'
  129.  
  130. #define    EOS    '\0'
  131.  
  132. #define isslash(c) ((c) == '\\' || (c) == '/')
  133.  
  134. static char *
  135. rangematch(char *pattern, char test)
  136. {
  137.   char c, c2;
  138.   int negate, ok;
  139.  
  140.   if ((negate = (*pattern == '!')) != 0)
  141.     ++pattern;
  142.  
  143.   /*
  144.    * TO DO: quoting
  145.    */
  146.  
  147.   for (ok = 0; (c = *pattern++) != ']';)
  148.   {
  149.     if (c == EOS)
  150.       return(NULL);        /* illegal pattern */
  151.     if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']')
  152.     {
  153.       if (c <= test && test <= c2)
  154.     ok = 1;
  155.       else if (isalpha(test) && c <= (test^0x20) && (test^0x20) <= c2)
  156.     ok = 1;
  157.       pattern += 2;
  158.     }
  159.     else if (tolower(c) == tolower(test))
  160.       ok = 1;
  161.   }
  162.   return(ok == negate ? NULL : pattern);
  163. }
  164.  
  165. static int hasdot;
  166.  
  167. static int
  168. fnmatch(char *pattern,
  169.     char *string)
  170. {
  171.   register char c;
  172.   char test, *rangematch();
  173.  
  174.   for (;;)
  175.     switch (c = *pattern++)
  176.     {
  177.     case EOS:
  178.       return(*string == EOS);
  179.     case '?':
  180.       if ((test = *string++) == EOS ||
  181.       isslash(test))
  182.     return(0);
  183.       break;
  184.     case '*':
  185.       c = *pattern;
  186.       /* collapse multiple stars */
  187.       while (c == '*')
  188.     c = *++pattern;
  189.  
  190.       /* optimize for pattern with * at end or before / */
  191.       if (c == EOS || (c == '.' && pattern[1] == EOS && !hasdot))
  192.     return(!strchr(string, '/'));
  193.       else if (isslash(c))
  194.       {
  195.     if ((string = strpbrk(string, "/\\")) == NULL)
  196.       return(0);
  197.     break;
  198.       }
  199.  
  200.       /* general case, use recursion */
  201.       while ((test = *string) != EOS)
  202.       {
  203.     if (fnmatch(pattern, string))
  204.       return(1);
  205.     if (isslash(test))
  206.       break;
  207.     ++string;
  208.       }
  209.       return(0);
  210.     case '[':
  211.       if ((test = *string++) == EOS ||
  212.       isslash(test))
  213.     return(0);
  214.       if ((pattern = rangematch(pattern, test)) == NULL)
  215.     return(0);
  216.       break;
  217.     default:
  218.       string++;
  219.       if (tolower(c) != tolower(string[-1]))
  220.     return(0);
  221.       break;
  222.     }
  223. }
  224.  
  225.  
  226.  
  227. #define PATH_MAX 140
  228.  
  229. static int lowcase = 0;
  230. static int mustexist = 0;
  231.  
  232. static void
  233. wildcard1(char *buf, char *bp, char *fp)
  234. {
  235.   char *slpos = strpbrk(fp, "/\\"), slsave='-';
  236.   int done, i;
  237.   struct ffblk ff;
  238.   char *wildchars;
  239.   if (slpos)
  240.   {
  241.     slsave = *slpos;
  242.     *slpos = 0;
  243.   }
  244.   for (i=0; fp[i]; i++)
  245.   {
  246.     if (islower(fp[i]))
  247.       lowcase = 1;
  248.     if (isupper(fp[i]))
  249.       lowcase = 0;
  250.   }
  251.   wildchars =  strpbrk(fp, "*?[]");
  252.   if (!expand_wildcards || wildchars==0)
  253.   {
  254.     strcpy(bp, fp);
  255.     if (slpos)
  256.     {
  257.       int bpl = strlen(bp);
  258.       bp[bpl++] = slsave;
  259.       bp[bpl] = 0;
  260.       wildcard1(buf, bp+bpl, slpos+1);
  261.     }
  262.     else
  263.     {
  264.       if (wildchars == 0 && mustexist)
  265.       {
  266.     if (access(buf, 0) == 0)
  267.       stash_arg(buf);
  268.       }
  269.       else
  270.     stash_arg(buf);
  271.     }
  272.   }
  273.   else
  274.   {
  275.     strcpy(bp, "*.*");
  276.     done = findfirst(buf, &ff, FA_RDONLY|FA_DIREC|FA_ARCH);
  277.     while (!done)
  278.     {
  279.       if (ff.ff_name[0] != '.' || fp[0] == '.')
  280.       {
  281.     if (lowcase)
  282.       strlwr(ff.ff_name);
  283.     hasdot = strchr(ff.ff_name, '.')!=0;
  284.     if (fnmatch(fp, ff.ff_name))
  285.     {
  286.       strcpy(bp, ff.ff_name);
  287.       if (slpos)
  288.       {
  289.         int bpl = strlen(bp);
  290.         bp[bpl++] = slsave;
  291.         bp[bpl] = 0;
  292.         mustexist++;
  293.         wildcard1(buf, bp+bpl, slpos+1);
  294.         mustexist--;
  295.       }
  296.       else
  297.         stash_arg(buf);
  298.     }
  299.       }
  300.       done = findnext(&ff);
  301.     }
  302.   }
  303.   if (slpos)
  304.     *slpos = slsave;
  305. }
  306.  
  307. static int
  308. argv_cmp(void *av, void *bv)
  309. {
  310.   register char *a = *(char **)av;
  311.   register char *b = *(char **)bv;
  312.   return strcmp(a, b);
  313. }
  314.  
  315. static void
  316. wildcard(char *arg)
  317. {
  318.   char buf[140];
  319.   char *bp, *fp;
  320.   int oarg;
  321.  
  322.   lowcase = 1;
  323.   bp=buf;
  324.   fp=arg;
  325.   if (fp[1] == ':')
  326.   {
  327.     *bp++ = *fp++;
  328.     *bp++ = *fp++;
  329.   }
  330.   if (*fp == '/' || *fp == '\\')
  331.     *bp++ = *fp++;
  332.   oarg = __glob_argc;
  333.   if (oarg < 1) oarg = 1;
  334.   wildcard1(buf, bp, fp);
  335.   if (oarg >= __glob_argc)
  336.     stash_arg(arg);
  337.   else
  338.     qsort(__glob_argv+oarg, __glob_argc - oarg,
  339.       sizeof(char *), argv_cmp);
  340. }
  341.  
  342. static void
  343. expand_arg(char *arg)
  344. {
  345.   if (arg[0] == '@')
  346.   {
  347.     FILE *f = fopen(arg+1, "r");
  348.     if (f)
  349.     {
  350.       parse_chars(f, file_getc);
  351.       fclose(f);
  352.       return;
  353.     }
  354.   }
  355.   else if (expand_wildcards && strspn("*?[]", arg))
  356.     wildcard(arg);
  357.   else
  358.     stash_arg(arg);
  359. }
  360.  
  361. static void
  362. parse_chars(void *ptr, int (*func)(void *ptr))
  363. {
  364.   int quote = 0;
  365.   int needs_expansion = 0;
  366.   char argbuf[1000];
  367.   char *start = argbuf;
  368.   int pending_arg = 0;
  369.   int done = 0;
  370.   int unc = -2;
  371.  
  372.   while (!done)
  373.   {
  374.     int c = (unc==-2) ? func(ptr) : unc;
  375.     unc = -2;
  376.     if (c <= 0)
  377.     {
  378.       if (pending_arg)
  379.       {
  380.     *start = 0;
  381.     if (needs_expansion)
  382.       expand_arg(argbuf);
  383.     else
  384.       stash_arg(argbuf);
  385.     pending_arg = 0;
  386.     start = argbuf;
  387.       }
  388.       done = 1;
  389.     }
  390.     else if (quote == SINGLE_QUOTE)
  391.     {
  392.       if (c == SINGLE_QUOTE)
  393.     quote = 0;
  394.       else
  395.     *start++ = c;
  396.     }
  397.     else if (quote == DOUBLE_QUOTE)
  398.     {
  399.       if (c == DOUBLE_QUOTE)
  400.     quote = 0;
  401.       else if (c == '\\')
  402.       {
  403.     unc = func(ptr);
  404.     if (strchr("\\'\"", unc))
  405.     {
  406.       *start++ = unc;
  407.       unc = -2;
  408.     }
  409.     else if (unc != '\n')
  410.     {
  411.       *start++ = c;
  412.     }
  413.       }
  414.       else
  415.     *start++ = c;
  416.     }
  417.     else if (isspace(c))
  418.     {
  419.       if (pending_arg)
  420.       {
  421.     *start = 0;
  422.     if (needs_expansion)
  423.       expand_arg(argbuf);
  424.     else
  425.       stash_arg(argbuf);
  426.     pending_arg = 0;
  427.     start = argbuf;
  428.       }
  429.     }
  430.     else
  431.     {
  432.       if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE)
  433.     quote = c;
  434.       else if (c == '\\')
  435.       {
  436.     unc = func(ptr);
  437.     if (unc == '\n')
  438.       unc = -2;
  439.     else if (strchr("\\'\"", unc) || isspace(unc))
  440.     {
  441.       *start++ = unc;
  442.       unc = -2;
  443.     }
  444.     else
  445.       *start++ = '\\';
  446.       }
  447.       else
  448.       {
  449.     if (strchr("*?[]", c) || (c == '@' && start == argbuf))
  450.       needs_expansion = 1;
  451.     *start++ = c;
  452.       }
  453.       pending_arg = 1;
  454.     }
  455.   }
  456. }
  457.  
  458. static int
  459. getenvargs(void)
  460. {
  461.   int i, ac;
  462.   char aname[10];
  463.   char *a0 = getenv("_argc");
  464.   if (!a0)
  465.     return 1;
  466.   ac = atoi(a0);
  467.   for (i=0; i<ac; i++)
  468.   {
  469.     sprintf(aname, "_argv%d", i);
  470.     if (i == 0)
  471.       stash_arg_at(getenv(aname), 0, 1);
  472.     else
  473.       expand_arg(getenv(aname));
  474.   }
  475.   return 0;
  476. }
  477.  
  478. void
  479. __glob_args(char *cmdline, char *dos_argv0, int _expand_wildcards)
  480. {
  481.   expand_wildcards = _expand_wildcards;
  482.   free_args();
  483.   __glob_argc = 0;
  484.   __glob_proxy_count = 0;
  485.  
  486.   if (getenvargs())
  487.   {
  488.     parse_chars(&cmdline, string_getc);
  489.  
  490.     if (__glob_argc > 4 && strcmp(__glob_argv[1], "!proxy") == 0)
  491.     {
  492.       int i;
  493.       for (i=0; i+2 < __glob_argc; i++)
  494.       {
  495.     unsigned long pval = strtoul(__glob_argv[i+2], 0, 16);
  496.     __glob_proxy_vals[i] = (unsigned) pval;
  497.       }
  498.       free_args();
  499.       __glob_proxy_count = i;
  500.       if (__glob_sense_expand_from_proxy)
  501.     expand_wildcards = __glob_sense_expand_from_proxy(expand_wildcards);
  502.       stash_arg_at(get_proxy(0), 0, 1);
  503.       for (i=1; i<__glob_proxy_vals[0]; i++)
  504.     expand_arg(get_proxy(i));
  505.     }
  506.     else
  507.       stash_arg_at(dos_argv0, 0, 1);
  508.   }
  509.  
  510.   stash_arg_at(0, __glob_argc, 0);
  511. }
  512.  
  513. void
  514. __glob_env(char *app_name)
  515. {
  516.   FILE *djgpp_env;
  517.   char *djgpp_var = getenv("DJGPP");
  518.   char *copy;
  519.  
  520.   if (djgpp_var)
  521.   {
  522.     djgpp_env = fopen(djgpp_var, "rt");
  523.     if (djgpp_env)
  524.     {
  525.       char line[2000];
  526.       char base[12], *bp, *a0p, *tb = (char *)line;
  527.       int this_prog = 1;
  528.       base[0] = '[';
  529.       bp = app_name;
  530.       for (a0p = bp; *a0p; a0p++)
  531.     if (strchr("\\/:", *a0p))
  532.       bp = a0p+1;
  533.       for (a0p=base+1; *bp && *bp != '.';)
  534.     *a0p++ = tolower(*bp++);
  535.       *a0p++ = ']';
  536.       *a0p++ = 0;
  537.       while (fgets(tb, 2000, djgpp_env))
  538.       {
  539.     tb[strlen(tb)-1] = 0;
  540.     if (tb[0] == 0)
  541.       continue;
  542.     if (tb[0] == '[')
  543.     {
  544.       if (strcmp(tb, base) == 0)
  545.         this_prog = 1;
  546.       else
  547.         this_prog = 0;
  548.     }
  549.     else
  550.     {
  551.       if (this_prog)
  552.       {
  553.         char *tb2 = tb+strlen(tb)+1;
  554.         char *sp=tb, *dp=tb2;
  555.         while (*sp != '=')
  556.           *dp++ = *sp++;
  557.         if (*tb2 == '+')    /* non-overriding */
  558.         {
  559.           *dp = 0;
  560.           tb2++;
  561.           if (getenv(tb2))
  562.         continue;    /* while fread */
  563.         }
  564.         *dp++ = *sp++;    /* copy the '=' */
  565.         while (*sp)
  566.         {
  567.           if (*sp == '%')
  568.           {
  569.         char *pp;
  570.         if (sp[1] == '%')
  571.         {
  572.           *dp++ = '%';
  573.           sp += 2;
  574.         }
  575.         else
  576.         {
  577.           char ps, *e, *dirend;
  578.           int dirpart=0, apsemi=0;
  579.           int mapup=0, maplow=0, mapfs=0, mapbs=0;
  580.           while (strchr(":;/\\<>", sp[1]))
  581.           {
  582.             switch (sp[1])
  583.             {
  584.             case ':':  dirpart=1; break;
  585.             case ';':  apsemi=1;  break;
  586.             case '/':  mapfs=1;   break;
  587.             case '\\': mapbs=1;   break;
  588.             case '<':  mapup=1;   break;
  589.             case '>':  maplow=1;  break;
  590.             }
  591.             sp++;
  592.           }
  593.           for (pp=sp+1; *pp && *pp != '%'; pp++);
  594.           ps = *pp;
  595.           *pp = 0;
  596.           e = getenv(sp+1);
  597.           dirend = dp;
  598.           if (e)
  599.           {
  600.             while (*e)
  601.             {
  602.               char ec = *e++;
  603.               if (strchr("\\/:", ec))
  604.             dirend=dp;
  605.               if (mapup) ec = toupper(ec);
  606.               if (maplow) ec = tolower(ec);
  607.               if (mapfs && ec == '\\') ec = '/';
  608.               if (mapbs && ec == '/') ec = '\\';
  609.               *dp++ = ec;
  610.             }
  611.           }
  612.           if (dirpart)
  613.             dp = dirend;
  614.           if (apsemi && e)
  615.             *dp++ = ';';
  616.           if (ps == 0)
  617.             break;
  618.           sp = pp+1;
  619.         }
  620.           }
  621.           else
  622.         *dp++ = *sp++;
  623.         }
  624.         *dp++ = 0;
  625.         copy = strdup(tb2);
  626.         if (!copy)
  627.         {
  628.           fprintf(stderr, "Error: out of memory gathering environment\n");
  629.           exit(1);
  630.         }
  631.         putenv(copy);
  632.       }
  633.     }
  634.       }
  635.       fclose(djgpp_env);
  636.     }
  637.   }
  638. }
  639.